// src/utils/dateUtil.ts

/**
 * 时间格式化选项
 */
export interface DateFormatOptions {
    timestamp?: number | string | Date;
    format?: string;
}

/**
 * 相对时间选项
 */
export interface RelativeTimeOptions {
    timestamp?: number | string | Date;
    withSuffix?: boolean;
}

/**
 * 时间范围类型
 */
export type TimeRange = {
    start: Date;
    end: Date;
};

/**
 * 时间工具类
 * 支持多种时间格式转换和常用时间操作
 */
export class DateUtil {
    /**
     * 格式化时间戳为指定格式
     * @param timestamp - 时间戳（毫秒）或Date对象
     * @param format - 格式字符串，默认 'yyyy-mm-dd HH:MM:ss'
     * @returns 格式化后的时间字符串
     */
    static formatTime(
        timestamp?: number | string | Date | null,
        format: string = 'yyyy-mm-dd HH:MM:ss'
    ): string {
        if (!timestamp) return '';

        const date = this.parseTimestamp(timestamp);
        if (!date) return '';

        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const day = date.getDate();
        const hours = date.getHours();
        const minutes = date.getMinutes();
        const seconds = date.getSeconds();

        // 格式化替换
        return format
            .replace('yyyy', year.toString())
            .replace('mm', month.toString().padStart(2, '0'))
            .replace('dd', day.toString().padStart(2, '0'))
            .replace('HH', hours.toString().padStart(2, '0'))
            .replace('MM', minutes.toString().padStart(2, '0'))
            .replace('ss', seconds.toString().padStart(2, '0'))
            .replace('M', month.toString())
            .replace('d', day.toString())
            .replace('H', hours.toString());
    }

    /**
     * 获取相对时间描述（如：刚刚、5分钟前、昨天等）
     * @param timestamp - 时间戳或Date对象
     * @param withSuffix - 是否包含后缀（如：前、后）
     * @returns 相对时间描述
     */
    static getRelativeTime(
        timestamp?: number | string | Date | null,
        withSuffix: boolean = true
    ): string {
        if (!timestamp) return '';

        const date = this.parseTimestamp(timestamp);
        if (!date) return '';

        const now = new Date();
        const diff = now.getTime() - date.getTime();
        const diffSeconds = Math.floor(diff / 1000);
        const diffMinutes = Math.floor(diffSeconds / 60);
        const diffHours = Math.floor(diffMinutes / 60);
        const diffDays = Math.floor(diffHours / 24);

        if (diffSeconds < 60) {
            return withSuffix ? '刚刚' : '刚刚';
        } else if (diffMinutes < 60) {
            return withSuffix ? `${diffMinutes}分钟前` : `${diffMinutes}分钟`;
        } else if (diffHours < 24) {
            return withSuffix ? `${diffHours}小时前` : `${diffHours}小时`;
        } else if (diffDays === 1) {
            return '昨天';
        } else if (diffDays === 2) {
            return '前天';
        } else if (diffDays < 7) {
            return withSuffix ? `${diffDays}天前` : `${diffDays}天`;
        } else {
            return this.formatTime(date, 'yyyy-mm-dd');
        }
    }

    /**
     * 获取简洁时间格式（今天显示时间，昨天显示昨天，其他显示日期）
     * @param timestamp - 时间戳或Date对象
     * @returns 简洁时间描述
     */
    static getSmartTime(timestamp?: number | string | Date | null): string {
        if (!timestamp) return '';

        const date = this.parseTimestamp(timestamp);
        if (!date) return '';

        const now = new Date();
        const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
        const yesterday = new Date(today);
        yesterday.setDate(yesterday.getDate() - 1);

        if (date >= today) {
            // 今天：显示时间
            return this.formatTime(date, 'HH:MM');
        } else if (date >= yesterday) {
            // 昨天：显示昨天 + 时间
            return `昨天 ${this.formatTime(date, 'HH:MM')}`;
        } else if (date.getFullYear() === now.getFullYear()) {
            // 今年：显示月日 + 时间
            return this.formatTime(date, 'mm-dd HH:MM');
        } else {
            // 其他年份：显示年月日 + 时间
            return this.formatTime(date, 'yyyy-mm-dd HH:MM');
        }
    }

    /**
     * 解析时间戳为Date对象
     * @param timestamp - 时间戳或Date对象
     * @returns Date对象或null
     */
    static parseTimestamp(timestamp: number | string | Date): Date | null {
        if (timestamp instanceof Date) {
            return timestamp;
        }

        let ts: number;
        if (typeof timestamp === 'string') {
            // 尝试解析字符串
            const parsed = Date.parse(timestamp);
            if (!isNaN(parsed)) {
                return new Date(parsed);
            }
            ts = parseInt(timestamp);
        } else {
            ts = timestamp;
        }

        // 判断是秒级还是毫秒级时间戳
        const date = new Date(ts < 10000000000 ? ts * 1000 : ts);

        // 验证日期是否有效
        if (isNaN(date.getTime())) {
            console.warn('Invalid timestamp:', timestamp);
            return null;
        }

        return date;
    }

    /**
     * 获取当前时间戳（毫秒）
     * @returns 当前时间戳
     */
    static now(): number {
        return Date.now();
    }

    /**
     * 获取当前时间戳（秒）
     * @returns 当前时间戳（秒）
     */
    static nowSeconds(): number {
        return Math.floor(Date.now() / 1000);
    }

    /**
     * 获取日期部分（去除时间）
     * @param date - 日期对象或时间戳
     * @returns 日期部分
     */
    static getDatePart(date?: Date | number | string | null): Date | null {
        if (!date) return null;

        const d = this.parseTimestamp(date);
        if (!d) return null;

        return new Date(d.getFullYear(), d.getMonth(), d.getDate());
    }

    /**
     * 判断两个日期是否是同一天
     * @param date1 - 第一个日期
     * @param date2 - 第二个日期
     * @returns 是否是同一天
     */
    static isSameDay(
        date1?: Date | number | string | null,
        date2?: Date | number | string | null
    ): boolean {
        if (!date1 || !date2) return false;

        const d1 = this.getDatePart(date1);
        const d2 = this.getDatePart(date2);

        if (!d1 || !d2) return false;

        return d1.getTime() === d2.getTime();
    }

    /**
     * 添加时间
     * @param date - 基础日期
     * @param amount - 数量
     * @param unit - 时间单位
     * @returns 新的日期
     */
    static addTime(
        date: Date | number | string,
        amount: number,
        unit: 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years' = 'days'
    ): Date | null {
        const d = this.parseTimestamp(date);
        if (!d) return null;

        const result = new Date(d);

        switch (unit) {
            case 'seconds':
                result.setSeconds(result.getSeconds() + amount);
                break;
            case 'minutes':
                result.setMinutes(result.getMinutes() + amount);
                break;
            case 'hours':
                result.setHours(result.getHours() + amount);
                break;
            case 'days':
                result.setDate(result.getDate() + amount);
                break;
            case 'months':
                result.setMonth(result.getMonth() + amount);
                break;
            case 'years':
                result.setFullYear(result.getFullYear() + amount);
                break;
        }

        return result;
    }

    /**
     * 计算两个日期之间的差值
     * @param date1 - 第一个日期
     * @param date2 - 第二个日期
     * @param unit - 时间单位
     * @returns 差值
     */
    static diff(
        date1: Date | number | string,
        date2: Date | number | string,
        unit: 'seconds' | 'minutes' | 'hours' | 'days' = 'days'
    ): number | null {
        const d1 = this.parseTimestamp(date1);
        const d2 = this.parseTimestamp(date2);

        if (!d1 || !d2) return null;

        const diffMs = Math.abs(d1.getTime() - d2.getTime());

        switch (unit) {
            case 'seconds':
                return Math.floor(diffMs / 1000);
            case 'minutes':
                return Math.floor(diffMs / (1000 * 60));
            case 'hours':
                return Math.floor(diffMs / (1000 * 60 * 60));
            case 'days':
                return Math.floor(diffMs / (1000 * 60 * 60 * 24));
            default:
                return diffMs;
        }
    }

    /**
     * 获取星期几
     * @param date - 日期
     * @param isShort - 是否简写
     * @returns 星期几
     */
    static getDayOfWeek(
        date?: Date | number | string | null,
        isShort: boolean = false
    ): string {
        if (!date) return '';

        const d = this.parseTimestamp(date);
        if (!d) return '';

        const weekDays = isShort
            ? ['日', '一', '二', '三', '四', '五', '六']
            : ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];

        return weekDays[d.getDay()];
    }

    /**
     * 格式化时间范围
     * @param start - 开始时间
     * @param end - 结束时间
     * @param format - 格式
     * @returns 格式化后的时间范围字符串
     */
    static formatTimeRange(
        start: Date | number | string,
        end: Date | number | string,
        format: string = 'yyyy-mm-dd HH:MM'
    ): string {
        const startDate = this.parseTimestamp(start);
        const endDate = this.parseTimestamp(end);

        if (!startDate || !endDate) return '';

        if (this.isSameDay(startDate, endDate)) {
            // 同一天：显示日期 + 开始时间～结束时间
            return `${this.formatTime(startDate, 'yyyy-mm-dd')} ${this.formatTime(startDate, 'HH:MM')}～${this.formatTime(endDate, 'HH:MM')}`;
        } else {
            // 不同天：显示完整时间范围
            return `${this.formatTime(startDate, format)}～${this.formatTime(endDate, format)}`;
        }
    }
}

// 默认导出
export default DateUtil;

// 常用格式的快捷方法
export const formatDate = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'yyyy-mm-dd');

export const formatTime = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'HH:MM:ss');

export const formatDateTime = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'yyyy-mm-dd HH:MM:ss');

export const formatDateTime1 = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'yyyy-mm-dd HH:MM');

export const formatShortTime = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'mm-dd');

export const formatShortDate = (timestamp?: number | string | Date | null) =>
    DateUtil.formatTime(timestamp, 'mm-dd HH:MM');


/**
 * 根据给定时间戳返回对应的友好时间字符串
 * @param {number|Date} t 支持时间戳或 Date 对象
 * @returns {string}
 */
export function friendlyTime(t) {
    if(!t){
        return ''
    }
    const now = new Date();
    const target = new Date(t);

    const pad = (n) => (n < 10 ? '0' + n : n);

    // 今天：只显示时分
    if (
        target.getFullYear() === now.getFullYear() &&
        target.getMonth() === now.getMonth() &&
        target.getDate() === now.getDate()
    ) {
        return `${pad(target.getHours())}:${pad(target.getMinutes())}`;
    }

    // 昨天：显示“昨天”
    const yesterday = new Date(now);
    yesterday.setDate(now.getDate() - 1);
    if (
        target.getFullYear() === yesterday.getFullYear() &&
        target.getMonth() === yesterday.getMonth() &&
        target.getDate() === yesterday.getDate()
    ) {
        return '昨天';
    }

    // 本周（周一为第一天）
    const getWeekStart = (d) => {
        const day = d.getDay() || 7; // 把周日 0 → 7
        const start = new Date(d);
        start.setDate(d.getDate() - day + 1);
        start.setHours(0, 0, 0, 0);
        return start;
    };
    const weekStart = getWeekStart(now);
    if (target >= weekStart) {
        const weekMap = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
        return weekMap[target.getDay()];
    }

    // 今年：MM-DD
    if (target.getFullYear() === now.getFullYear()) {
        return `${pad(target.getMonth() + 1)}-${pad(target.getDate())}`;
    }

    // 非今年：YYYY-MM-DD
    return `${target.getFullYear()}-${pad(target.getMonth() + 1)}-${pad(
        target.getDate()
    )}`;
}